﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Practices.Prism.PubSubEvents;
using Hopscotch.Presentation.Configuration;
using Hopscotch.Common.Contracts.AppService;
using Hopscotch.Application.Shell.Login;
using Hopscotch.Test.Presentation.Threading;
using Hopscotch.Presentation.Common.Threading;
using FluentAssertions;
using Moq;
using NUnit.Framework;

namespace Hopscotch.Application.Shell.Test
{
    [TestFixture]
    public class LoginViewModelTest
    {
        private LoginViewModel loginViewModel;
        private LoginInfo loginInfo;
        private int MaxWaitTime = 1000;

        [SetUp]
        public void SetUp()
        {
            IEventAggregator eventAggregator = new EventAggregator();
            Mock<IEnvironmentsConfiguration> environmentsConfiguration
                = new Mock<IEnvironmentsConfiguration>();

            loginInfo = new LoginInfo();
            loginViewModel = new LoginViewModel(eventAggregator, environmentsConfiguration.Object, loginInfo);
        }

        [Test]
        public void TestSignalDefaultIsUnset()
        {
            loginInfo.Signal.IsSet.Should().BeFalse();
        }

        [Test]
        public void TestLoginSuccessDefaultIsFalse()
        {
            loginInfo.LoginSuccess.Should().BeFalse();
        }

        [Test]
        public void TestSignalIsSetAfterClose()
        {
            loginViewModel.Close(false);
            loginInfo.Signal.IsSet.Should().BeTrue();
        }

        private void Login(LoginViewModel loginViewModel, bool loginSucess)
        {
            Mock<IAuthenticationService> mockAuthenticationService = new Mock<IAuthenticationService>();
            Mock<IEnvironmentConfiguration> mockEnvironmentConfiguration = new Mock<IEnvironmentConfiguration>();

            mockAuthenticationService.Setup(s => s.Login(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(loginSucess);

            loginViewModel.Login(mockAuthenticationService.Object, mockEnvironmentConfiguration.Object, null, null);
        }

        [Test]
        public void TestSignalIsSetAfterLoginSuccess()
        {
            Login(loginViewModel, true);

            loginInfo.Signal.Wait(MaxWaitTime);
            loginInfo.Signal.IsSet.Should().BeTrue();
            loginInfo.LoginSuccess.Should().BeTrue();
        }

        [Test]
        public void TestStatusMessageIsResetAfterLoginSuccess()
        {
            Login(loginViewModel, true);

            loginInfo.Signal.Wait(MaxWaitTime);
            loginViewModel.StatusMessage.Should().BeNull();
        }

        [Test]
        public void TestIsBusyIsSetAfterLoginSuccess()
        {
            Login(loginViewModel, true);

            loginInfo.Signal.Wait(MaxWaitTime);
            loginViewModel.IsBusy.Should().BeTrue();
        }

        [Test]
        public void TestPropertyIsBusyRaisesChangedEvent()
        {
            loginViewModel.MonitorEvents();
            loginViewModel.IsBusy = !loginViewModel.IsBusy;
            loginViewModel.ShouldRaisePropertyChangeFor(c => c.IsBusy);
        }
    }
}
